home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / das / sect.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  15KB  |  669 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  SECT.C
  9.  */
  10.  
  11. #include "defs.h"
  12.  
  13. Prototype Sect    *CurSection;
  14. Prototype Sect    *SectBase;
  15. Prototype Sect    **LastSect;
  16. Prototype short Hunks;
  17.  
  18. Prototype void    InitSect(void);
  19. Prototype void    ResetSectAddrs(void);
  20. Prototype void    HandleInstReloc(Sect *, Label *, long, short, long);
  21. Prototype void    DumpSectionData(Sect *, void *, long);
  22. Prototype void    NewSection(char *);
  23. Prototype void    SectCreateObject(FILE *, char *);
  24. Prototype void    CreateHunkReloc(FILE *, long, Reloc *);
  25. Prototype void    DumpRelocs(FILE *, Reloc *, long, long);
  26. Prototype void    CreateExtHunkReloc(FILE *, ubyte, Reloc *);
  27. Prototype void    DumpExtReloc(FILE *, Reloc *, long, Label *, long);
  28. Prototype void    CreateExportSDU(FILE *, ubyte, Label *);
  29. Prototype void    CreateSymbols(FILE *, Label *);
  30. Prototype void    zwrite(FILE *, long);
  31.  
  32. Sect    *CurSection;
  33. Sect    *SectBase;
  34. Sect    **LastSect;
  35. short    Hunks;
  36. static long Ary[64];
  37.  
  38. void
  39. InitSect()
  40. {
  41.     LastSect = &SectBase;
  42.     NewSection(strdup("____DUMMY____,code"));
  43.     Hunks = 0;
  44.     CurSection->Type = SECT_DUMMY;
  45.     DebugLineNo = 0;
  46. }
  47.  
  48. void
  49. ResetSectAddrs()
  50. {
  51.     Sect *sect;
  52.     for (sect = SectBase; sect; sect = sect->Next)
  53.     sect->Addr = 0;
  54.     DebugLineNo = 0;
  55. }
  56.  
  57. /*
  58.  *  Create a relocation entry and add it to the section.
  59.  */
  60.  
  61. void
  62. HandleInstReloc(
  63.     Sect *sect,     /* section this occurs in    */
  64.     Label *label,    /* label in question        */
  65.     long offset,     /* offset in section sect of info to be relocated */
  66.     short size,     /* size of information needing relocation      */
  67.     long reloc_type    /* type of relocation        */
  68. ) {
  69.     Reloc *reloc = AllocStructure(Reloc);
  70.     Reloc **list = sect->RelocAry;
  71.     /*Reloc **scan;*/
  72.  
  73.     dbprintf(0, ("@%04lx Reloc %s sect %s size %d\n", offset, label->Name, sect->Name, size));
  74.  
  75.     reloc->Label = label;
  76.     reloc->Offset = offset;
  77.  
  78.     if (label->l_Type == LT_EXT)
  79.     list += RA_EXT;
  80.  
  81.     switch(size | reloc_type) {
  82.     case 4 | RELOC_PCREL:    /*  long-pc-relative        */
  83.     ++list;
  84.     case 2 | RELOC_DATAREL:    /*  word-data reloc        */
  85.     ++list;
  86.     case 4:            /*  long-absolute        */
  87.     ++list;
  88.     case 2:            /*  absolute const reloc    */
  89.     case 2 | RELOC_PCREL:    /*  word-pc relative        */
  90.     ++list;
  91.     case 1:            /*  byte-pc relative?        */
  92.     break;
  93.     default:
  94.     cerror(EERROR_BAD_RELOC);
  95.     break;
  96.     }
  97.  
  98.     /*
  99.      *  Internal relocs must be sorted by hunk number so the dump routines
  100.      *  can group them together in output.
  101.      *
  102.      *  External relocs must be sorted by label.  THE LABEL->SECT FIELD IS
  103.      *  NULL FOR EXTERNAL RELOCS!
  104.      */
  105.  
  106.     if (label->l_Type != LT_EXT) {
  107.     while (*list && (*list)->Label->Sect->Hunk < label->Sect->Hunk)
  108.     list = &(*list)->RNext;
  109.  
  110.     while (*list && (*list)->Label->Sect->Hunk == label->Sect->Hunk) {
  111.         if ((*list)->Label == reloc->Label)
  112.         break;
  113.         list = &(*list)->RNext;
  114.     }
  115. #ifdef NOTDEF
  116.         for (scan = list;
  117.         *scan && (*scan)->Label->Sect->Hunk == label->Sect->Hunk;
  118.         scan = &(*scan)->RNext)
  119.     {
  120.     if ((*scan)->Label == reloc->Label) {
  121.         reloc->RNext = *scan;
  122.         *scan = reloc;
  123.         return;
  124.     }
  125.     }
  126. #endif
  127.     } else {
  128.     while (*list && (*list)->Label != reloc->Label)
  129.         list = &(*list)->RNext;
  130.     }
  131.     reloc->RNext = *list;
  132.     *list = reloc;
  133. }
  134.  
  135. /*
  136.  *  buf can be NULL, indicating DS or 0's
  137.  */
  138.  
  139. void
  140. DumpSectionData(sect, buf, bytes)
  141. Sect *sect;
  142. void *buf;
  143. long bytes;
  144. {
  145.     DBlock *block = sect->LastBlock;
  146.  
  147.     if (bytes < 0)
  148.     cerror(EFATAL_DUMPSECT_NEG);
  149.  
  150.     if (bytes == 0)
  151.     return;
  152.  
  153. #ifdef DEBUG
  154.     if (DDebug) {
  155.     if (buf) {
  156.         long i;
  157.         ubyte *ptr = (ubyte *)buf;
  158.         printf("@%04lx dump ", sect->Addr);
  159.         for (i = 0; i < bytes; i += 2) {
  160.         printf("%02x", *ptr++);
  161.         printf("%02x ", *ptr++);
  162.         }
  163.         printf("\n");
  164.     } else {
  165.         printf("@%04lx dump %ld bytes\n", sect->Addr, bytes);
  166.     }
  167.     }
  168. #endif
  169.  
  170.     if (block && bytes <= block->Max - block->Size) {
  171.     if (buf)
  172.         movmem(buf, (char *)block->Data + block->Size, bytes);
  173.     else
  174.         setmem((char *)block->Data + block->Size, bytes, 0);
  175.     block->Size += bytes;
  176.     sect->ObjLen += bytes;
  177.     sect->Addr   += bytes;
  178.     return;
  179.     }
  180.     if (buf == NULL) {
  181.     if (sect->Block == NULL) {
  182.         sect->ObjLen += bytes;
  183.         sect->Addr     += bytes;
  184.         return;
  185.     }
  186.     if (sect->LastBlock->Data == NULL) {
  187.         sect->LastBlock->Size += bytes;
  188.         sect->LastBlock->Max  += bytes;
  189.         sect->ObjLen += bytes;
  190.         sect->Addr += bytes;
  191.         return;
  192.     }
  193.     /*
  194.      *  fall through to append a dummy block.
  195.      */
  196.     }
  197.  
  198.     block = AllocStructure(DBlock);
  199.     block->Next = NULL;
  200.  
  201.     if (sect->LastBlock) {
  202.     sect->LastBlock->Next = block;
  203.     } else {
  204.     sect->Block = block;
  205.  
  206.     /*
  207.      *  This is the first real block
  208.      *
  209.      *  If there was previous bss data (i.e. no blocks but non-zero
  210.      *  object length) then create a dummy block whos buf is NULL
  211.      *  with the # of zeros to write.
  212.      */
  213.  
  214.     if (sect->ObjLen) {
  215.         block->Max = block->Size = sect->ObjLen;
  216.  
  217.         block = AllocStructure(DBlock);
  218.         sect->Block->Next = block;
  219.     }
  220.     }
  221.     sect->LastBlock = block;
  222.  
  223.     if (buf) {
  224.     block->Max = SECTBLKSIZE;
  225.     if (block->Max < bytes)
  226.         block->Max = bytes;
  227.     block->Data = malloc(block->Max);
  228.     if (block->Data == NULL)
  229.         NoMemory();
  230.     block->Size = bytes;
  231.     movmem(buf, (char *)block->Data, bytes);
  232.     } else {
  233.     block->Max = block->Size = bytes;
  234.     }
  235.     sect->ObjLen += bytes;
  236.     sect->Addr     += bytes;
  237. }
  238.  
  239. /*
  240.  *  [name],type[,$mask]     type is:    code,data,bss,abs
  241.  *                mask used for mem flags, resource flags
  242.  */
  243.  
  244. void
  245. NewSection(ops)
  246. char *ops;
  247. {
  248.     char *ptr = ops;
  249.     char *maskStr;
  250.     Sect *sect;
  251.     short type;
  252.     long mask = 0;
  253.  
  254.     while (*ptr && *ptr != ',')
  255.     ++ptr;
  256.     if (*ptr != ',') {
  257.     cerror(EERROR_BAD_SECTION_DIRECT);
  258.     NewSection(strdup("code,code"));    /*  to prevent program crash */
  259.     return;
  260.     }
  261.     *ptr++ = 0;
  262.     for (maskStr = ptr; *maskStr && *maskStr != ','; ++maskStr);
  263.     if (*maskStr == ',')
  264.     *maskStr++ = 0;
  265.  
  266.     if (*maskStr)
  267.     mask = ParseIntExp(maskStr);
  268.  
  269.     cvtstrtolower(ptr);
  270.  
  271.     type = SECT_CODE;
  272.     if (strcmp(ptr, "code") == 0)
  273.     type = SECT_CODE;
  274.     else if (strcmp(ptr, "data") == 0)
  275.     type = SECT_DATA;
  276.     else if (strcmp(ptr, "bss") == 0)
  277.     type = SECT_BSS;
  278.     else if (strcmp(ptr, "abs") == 0)
  279.     type = SECT_ABS;
  280.     else if (strncmp(ptr, "com", 3) == 0)
  281.     type = SECT_COMMON;
  282.     else
  283.     cerror(EERROR_BAD_SECTION_TYPE);
  284.  
  285.     /*
  286.      *    Does the section exist already?
  287.      */
  288.  
  289.     for (sect = SectBase; sect; sect = sect->Next) {
  290.     if (strcmp(ops, sect->Name) == 0 && sect->HunkMask == mask) {
  291.         if (sect->Type != type)
  292.         cerror(EERROR_SECTION_NAME_CONFLICT);
  293.         break;
  294.     }
  295.     }
  296.     if (sect == NULL) {
  297.     sect = AllocStructure(Sect);
  298.     sect->Name = ops;
  299.     sect->Type = type;
  300.     sect->Hunk = Hunks++;
  301.     sect->HunkMask = mask;
  302.  
  303.     *LastSect = sect;
  304.     LastSect = §->Next;
  305.     }
  306.     CurSection = sect;
  307. }
  308.  
  309. /*
  310.  *  Generate the object file.  Begin with a HUNK_UNIT containing the name
  311.  *  of the object file.  Continue with the following for EACH section:
  312.  *    -hunk_name
  313.  *    -hunk_code/data/bss
  314.  *    -hunk_reloc32
  315.  *    -hunk_reloc16
  316.  *    -hunk_reloc8
  317.  *    -hunk_ext    (external references and external defs, ordering:
  318.  *             extref32, extref16, extref8, extdef)
  319.  *    -hunk_symbol    (optional)
  320.  *    -hunk_debug    (optional)
  321.  *    -hunk_end    end of this hunk...
  322.  */
  323.  
  324. void
  325. SectCreateObject(fo, unitName)
  326. FILE *fo;
  327. char *unitName;
  328. {
  329.     Sect *sect;
  330.  
  331.     /*
  332.      *    hunk_unit
  333.      */
  334.     {
  335.     int len;
  336.     short i;
  337.     char c = 0;
  338.  
  339.     i = strlen(unitName);
  340.     while (i >= 0 && unitName[i] != '.')
  341.         --i;
  342.     if (NoUnitName)
  343.         i = 0;
  344.     if (i >= 0) {
  345.         c = unitName[i];
  346.         unitName[i] = 0;
  347.     }
  348.  
  349.     len = (strlen(unitName) + 3) >> 2;
  350.  
  351.     Ary[0] = ToMsbOrder(0x3E7);
  352.     Ary[1] = ToMsbOrder(len);
  353.     setmem(Ary + 2, len*4, 0);
  354.     strcpy((char *)(Ary + 2), unitName);
  355.     fwrite((char *)Ary, sizeof(long), len + 2, fo);
  356.     if (i >= 0)
  357.         unitName[i] = c;
  358.     }
  359.     /*
  360.      *    For each section...
  361.      */
  362.     for (sect = SectBase; sect; sect = sect->Next) {
  363.     if (sect->Type == SECT_DUMMY)
  364.         continue;
  365.     /*
  366.      *  hunk_name
  367.      */
  368.     {
  369.         int len = (strlen(sect->Name) + 3) >> 2;
  370.         Ary[0] = ToMsbOrder(0x3E8);
  371.         Ary[1] = ToMsbOrder(len);
  372.         setmem(Ary + 2, len*4, 0);
  373.         strcpy((char *)(Ary + 2), sect->Name);
  374.         fwrite((char *)Ary, sizeof(long), len + 2, fo);
  375.     }
  376.     /*
  377.      *  hunk_code,data, or bss
  378.      */
  379.     {
  380.         static long TConvAry[] = { 0, 0x3E9, 0x3EA, 0x3EB, 0x3EB, 0x3EB };
  381.  
  382.         Ary[0] = ToMsbOrder(TConvAry[sect->Type] | sect->HunkMask);
  383.  
  384.         if (sect->Type == SECT_COMMON)
  385.         Ary[1] = 0;
  386.         else
  387.         Ary[1] = ToMsbOrder((sect->ObjLen + 3) >> 2);
  388.  
  389.         fwrite((char *)Ary, sizeof(long), 2, fo);
  390.  
  391.         if (sect->Type != SECT_BSS && sect->Type != SECT_ABS && sect->Type != SECT_COMMON) {   /* if not BSS/COMMON */
  392.         DBlock *block;
  393.         int n;
  394.         if (sect->Block == NULL && sect->ObjLen)
  395.             zwrite(fo, sect->ObjLen);
  396.         for (block = sect->Block; block; block = block->Next) {
  397.             if (block->Data) {
  398.             fwrite((char *)block->Data, 1, block->Size, fo);
  399.             } else {
  400.             zwrite(fo, block->Size);
  401.             }
  402.         }
  403.  
  404.         /*
  405.          *  When forcing alignment align with NOPs in a CODE section.
  406.          */
  407.  
  408.         if ((n = AlignDelta(sect->ObjLen, 4)) != 0) {
  409.             if ((n & 1) == 0 && sect->Type == SECT_CODE) {
  410.             Ary[0] = ToMsbOrder(0x4E714E71);
  411.             } else {
  412.             Ary[0] = 0;
  413.             }
  414.             fwrite((char *)Ary, 1, n, fo);
  415.         }
  416.         }
  417.     }
  418.  
  419.     /*
  420.      *  local byte-pc, word-pc, long, and word-data reloc
  421.      */
  422.  
  423.     {
  424.         CreateHunkReloc(fo, 0x3EE, sect->r_ByteReloc);
  425.         CreateHunkReloc(fo, 0x3ED, sect->r_WordRelocPc);
  426.         CreateHunkReloc(fo, 0x3EC, sect->r_LongReloc);
  427.         CreateHunkReloc(fo, 0x3F8, sect->r_WordDataReloc);
  428.         CreateHunkReloc(fo, 0x400, sect->r_LongRelocPc);
  429.     }
  430.  
  431.     /*
  432.      *  external byte, word-pc, long, and word-data relocation
  433.      *
  434.      *  symbols
  435.      */
  436.  
  437.     if (sect->r_ExtByteReloc || sect->r_ExtWordRelocPc || sect->r_ExtLongReloc || sect->r_ExtWordDataReloc || sect->r_LongRelocPc || sect->XDefLab) {
  438.         Ary[0] = ToMsbOrder(0x3EF);
  439.         fwrite((char *)Ary, sizeof(long), 1, fo);
  440.  
  441.         CreateExtHunkReloc(fo, 134, sect->r_ExtWordDataReloc);
  442.         CreateExtHunkReloc(fo, 132, sect->r_ExtByteReloc);
  443.         CreateExtHunkReloc(fo, 131, sect->r_ExtWordRelocPc);
  444.         CreateExtHunkReloc(fo, 129, sect->r_ExtLongReloc);
  445.         CreateExtHunkReloc(fo, 135, sect->r_ExtLongRelocPc);
  446.         CreateExportSDU(fo, ((sect->Type == SECT_COMMON) ? 130 : 1), sect->XDefLab);
  447.         Ary[0] = ToMsbOrder(0);
  448.         fwrite((char *)Ary, sizeof(long), 1, fo);
  449.     }
  450.  
  451.     if (AddSym)
  452.     {
  453.         CreateSymbols(fo, sect->XDefLab);
  454.     }
  455.  
  456.     /*
  457.      *  hunk_debug
  458.      */
  459.  
  460.     if (sect->DebugAry && sect->DebugIdx) {
  461.         Ary[0] = ToMsbOrder(0x3F1);
  462.  
  463.         Ary[2] = ToMsbOrder(0);
  464.         Ary[3] = ToMsbOrder(0x4C494E45);  /* 'LINE'; */
  465.         Ary[4] = ToMsbOrder((strlen(SrcFileName) + 3) >> 2);
  466.  
  467.         setmem(Ary + 5, ToMsbOrder(Ary[4]) * 4, 0);
  468.         strcpy((char *)(Ary + 5), SrcFileName);
  469.  
  470.         Ary[1] = ToMsbOrder(sect->DebugIdx * 2 + 3 + FromMsbOrder(Ary[4]));
  471.  
  472.         fwrite((char *)Ary, sizeof(long), 5 + FromMsbOrder(Ary[4]), fo);
  473.         fwrite(sect->DebugAry, sizeof(DebugNode), sect->DebugIdx, fo);
  474.     }
  475.  
  476.     /*
  477.      *  hunk_end
  478.      */
  479.     {
  480.         Ary[0] = ToMsbOrder(0x3F2);
  481.         fwrite((char *)Ary, sizeof(long), 1, fo);
  482.     }
  483.     }
  484. }
  485.  
  486. void
  487. CreateHunkReloc(fo, hunk, reloc)
  488. FILE *fo;
  489. long hunk;
  490. Reloc *reloc;
  491. {
  492.     long n;
  493.     long t;
  494.     long baseHunk;
  495.     Reloc *base;
  496.  
  497.     if (reloc == NULL)
  498.     return;
  499.  
  500.     t = ToMsbOrder(hunk);
  501.     fwrite((char *)&t, sizeof(long), 1, fo);
  502.  
  503.     base = reloc;
  504.     baseHunk = reloc->Label->Sect->Hunk;
  505.     n = 0;
  506.  
  507.     while (reloc) {
  508.     if (baseHunk != reloc->Label->Sect->Hunk) {
  509.         DumpRelocs(fo, base, n, baseHunk);
  510.         baseHunk = reloc->Label->Sect->Hunk;
  511.         base = reloc;
  512.         n = 0;
  513.     }
  514.     ++n;
  515.     reloc = reloc->RNext;
  516.     }
  517.     if (n)
  518.     DumpRelocs(fo, base, n, baseHunk);
  519.  
  520.     t = ToMsbOrder(0);
  521.     fwrite((char *)&t, sizeof(long), 1, fo);
  522. }
  523.  
  524. void
  525. DumpRelocs(fo, base, n, baseHunk)
  526. FILE *fo;
  527. Reloc *base;
  528. long n;
  529. long baseHunk;
  530. {
  531.     long t;
  532.  
  533.     t = ToMsbOrder(n);
  534.     fwrite((char *)&t, sizeof(long), 1, fo);
  535.     t = ToMsbOrder(baseHunk);
  536.     fwrite((char *)&t, sizeof(long), 1, fo);
  537.  
  538.     while (n--) {
  539.         t = ToMsbOrder(base->Offset);
  540.     fwrite((char *)&t, sizeof(long), 1, fo);
  541.     base = base->RNext;
  542.     }
  543. }
  544.  
  545. void
  546. CreateExtHunkReloc(FILE *fo, ubyte type, Reloc *reloc)
  547. {
  548.     Reloc *base;
  549.     Label *baseLabel;
  550.     long n;
  551.  
  552.     if (reloc == NULL)
  553.     return;
  554.  
  555.     base = reloc;
  556.     baseLabel = reloc->Label;
  557.     n = 0;
  558.  
  559.     while (reloc) {
  560.     if (baseLabel != reloc->Label) {
  561.         DumpExtReloc(fo, base, n, baseLabel, type);
  562.         baseLabel = reloc->Label;
  563.         base = reloc;
  564.         n = 0;
  565.     }
  566.     ++n;
  567.     reloc = reloc->RNext;
  568.     }
  569.     if (n)
  570.     DumpExtReloc(fo, base, n, baseLabel, type);
  571. }
  572.  
  573. void
  574. DumpExtReloc(fo, base, n, label, type)
  575. FILE *fo;
  576. Reloc *base;
  577. long n;
  578. Label *label;
  579. long type;
  580. {
  581.     int len = (strlen(label->Name) + 3) >> 2;
  582.  
  583.     Ary[0] = ToMsbOrder((type << 24) | len);
  584.     setmem(Ary + 1, len*4, 0);
  585.     strcpy((char *)(Ary + 1), label->Name);
  586.  
  587.     Ary[1 + len] = ToMsbOrder(n);        /*  # references */
  588.  
  589.     fwrite((char *)Ary, sizeof(long), len + 2, fo);
  590.     while (n--) {
  591.         long t = ToMsbOrder(base->Offset);
  592.     fwrite((char *)&t, sizeof(long), 1, fo);
  593.     base = base->RNext;
  594.     }
  595. }
  596.  
  597. /*
  598.  *  XDEFs
  599.  */
  600.  
  601. void
  602. CreateExportSDU(FILE *fo, ubyte type, Label *label)
  603. {
  604.     while (label)
  605.     {
  606.     int len = (strlen(label->Name) + 3) >> 2;
  607.  
  608.     if (label->l_Type == LT_INT)
  609.         Ary[0] = ToMsbOrder((2 << 24) | len);
  610.     else
  611.         Ary[0] = ToMsbOrder((type << 24) | len);
  612.  
  613.     setmem(Ary + 1, len*4, 0);
  614.     strcpy((char *)(Ary + 1), label->Name);
  615.     Ary[1 + len] = ToMsbOrder(label->l_Offset);    /* Offset or Size */
  616.     fwrite((char *)Ary, sizeof(long), len + 2, fo);
  617.     label = label->XDefLink;
  618.     }
  619. }
  620.  
  621.  
  622. void
  623. CreateSymbols(FILE *fo, Label *label)
  624. {
  625.     int header = 0;
  626.  
  627.     while (label) {
  628.     int len = (strlen(label->Name) + 3) >> 2;
  629.  
  630.     if (label->l_Type != LT_INT)
  631.     {
  632.         if (header == 0)
  633.         {
  634.             Ary[0] = ToMsbOrder(0x3F0);
  635.             fwrite((char *)Ary, sizeof(long), 1, fo);
  636.             header = 1;
  637.             }
  638.  
  639.         Ary[0] = ToMsbOrder(len);
  640.  
  641.         setmem(Ary + 1, len*4, 0);
  642.         strcpy((char *)(Ary + 1), label->Name);
  643.         Ary[1 + len] = ToMsbOrder(label->l_Offset);   /* Offset or Size */
  644.         fwrite((char *)Ary, sizeof(long), len + 2, fo);
  645.     }
  646.     label = label->XDefLink;
  647.     }
  648.  
  649.     if (header)
  650.     {
  651.     Ary[0] = 0;
  652.     fwrite((char *)Ary, sizeof(long), 1, fo);
  653.     }
  654. }
  655.  
  656. void
  657. zwrite(fo, bytes)
  658. FILE *fo;
  659. long bytes;
  660. {
  661.     static char Zero[512];
  662.  
  663.     while (bytes > sizeof(Zero)) {
  664.     fwrite(Zero, 1, sizeof(Zero), fo);
  665.     bytes -= sizeof(Zero);
  666.     }
  667.     fwrite(Zero, 1, bytes, fo);
  668. }
  669.